package org.zoomdev.zoom.common.utils;

import org.zoomdev.zoom.common.exceptions.ZoomException;

import java.io.*;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

public final class LambdaMethodExtractor {


    public static String extractName(Serializable lambda) {
        SerializedLambda serializedLambda;
        try {
            serializedLambda = extractSerializedLambda(lambda);
            return serializedLambda.getImplMethodName();
        } catch (Exception e) {
            throw new ZoomException("解析lambda出错", e);
        }
    }

    /**
     * 通过序列化机制提取SerializedLambda对象
     */
    public static SerializedLambda extractSerializedLambda(Serializable lambda) throws Exception {

        // 尝试直接获取writeReplace方法（内部方法）
        Method writeReplace = null;
        try {
            writeReplace = lambda.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e) {
            // 获取失败时使用序列化方案
            return extractViaSerialization(lambda);
        }

        // 通过反射直接调用writeReplace方法
        try {
            writeReplace.setAccessible(true);
            return (SerializedLambda) writeReplace.invoke(lambda);
        } catch (Exception e) {
            // 反射失败时使用序列化方案
            return extractViaSerialization(lambda);
        }
    }

    /**
     * 通过对象序列化提取SerializedLambda对象
     */
    private static SerializedLambda extractViaSerialization(Serializable lambda) throws Exception {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {

            // 序列化Lambda对象
            oos.writeObject(lambda);
            oos.flush();

            try (ObjectInputStream ois = new ObjectInputStream(
                    new ByteArrayInputStream(baos.toByteArray()))) {

                // 读取序列化流会调用readResolve方法，返回SerializedLambda对象
                return (SerializedLambda) ois.readObject();
            }
        }
    }

    public static String extraGetterName(Serializable lambda) {
        SerializedLambda serializedLambda;
        try {
            serializedLambda = extractSerializedLambda(lambda);
            String name = serializedLambda.getImplMethodName();
            if (!name.startsWith("get") && !name.startsWith("is")) {
                throw new ZoomException("非标准getter");
            }
            String property = name.startsWith("is") ?
                    name.substring(2) :
                    name.substring(3); // 去掉 "get"
            return Character.toLowerCase(property.charAt(0)) + property.substring(1);
        } catch (Exception e) {
            throw new ZoomException("解析lambda出错", e);
        }
    }


}